import { CHARID, SERIVCEID } from './const';

const app = getApp()
  
export default {

    /**
     * 初始化蓝牙设备
     * */
    initBlueTooth() {
        return new Promise((resolve, reject) => {
            wx.closeBluetoothAdapter()
            this.offOnChange()
            // 初始化蓝牙模块
            wx.openBluetoothAdapter({
                success: (res) => {
                    console.log('初始化蓝牙模块成功', res)
                    resolve()
                },
                fail(err) {
                    console.log('初始化蓝牙模块失败', err)
                    let eCode = ''
                    if (err.errCode && err.errCode !== 10001) {
                        eCode = ' 错误码：' + err.errCode
                    }
                    let contentMsg = '初始化失败，请检查蓝牙是否已开启'
                    const { system } = wx.getSystemInfoSync()
                    if (system.toLocaleLowerCase().includes('ios')) {
                        contentMsg =
                            '初始化失败，请检查蓝牙是否已开启或检查是否打开蓝牙授权'
                    }
                    reject({
                        message: contentMsg + eCode,
                        detail: err
                    })
                }
            })
        })
    },

    /**
     * 初始化蓝牙设备并监听设备状态变化
     */
    startConnect() {
        return new Promise((resolve, reject) => {
            /* 获取蓝牙适配器状态
             * discovering  是否正在搜索设备
             * available  蓝牙适配器是否可用
             * */
            this.getBluetoothAdapterState()
                .then((res) => {
                    // const {available} = res
                    // if (available) {
                    //     console.log('蓝牙适配器可用，无需初始化')
                    //     resolve()
                    // } else {
                    console.log('蓝牙适配器不可用，初始化')
                    this.initBlueTooth()
                        .then((res) => {
                            resolve()
                        })
                        .catch((e) => {
                            reject(e)
                        })
                    // }
                })
                .catch((e) => {
                    console.log('蓝牙适配器不可用，初始化', e)
                    this.initBlueTooth()
                        .then(() => {
                            resolve()
                        })
                        .catch((e) => {
                            reject(e)
                        })
                })
        })
    },

    /**
     * 获取本机蓝牙适配器状态
     * https://developers.weixin.qq.com/miniprogram/dev/api/wx.getBluetoothAdapterState.html
     */
    getBluetoothAdapterState() {
        return new Promise((resolve, reject) => {
            wx.getBluetoothAdapterState({
                success: (res) => {
                    console.log('获取本机蓝牙适配器状态成功', res)
                    resolve(res)
                },
                fail: (e) => {
                    console.log('获取本机蓝牙适配器状态失败', e)
                    reject(e)
                }
            })
        })
    },

    /**
     * 搜索蓝牙设备
     * */
    startSearchBlueTooth(services = []) {
        return new Promise((resolve, reject) => {
            wx.startBluetoothDevicesDiscovery({
                services,
                allowDuplicatesKey: false,
                success: (res) => {
                    console.log('启动搜索蓝牙设备', res)
                    resolve(res)
                },
                fail: (err) => {
                    console.log('搜索蓝牙设备失败', err)
                    reject(err)
                }
            })
        })
    },

    /**
     * 停止搜索蓝牙设备
     * */
    stopSearchBlueTooth() {
        return new Promise((resolve, reject) => {
            wx.stopBluetoothDevicesDiscovery({
                success: (res) => {
                    console.log('停止搜索蓝牙设备', res)
                    resolve(res)
                },
                fail: (err) => {
                    console.log('停止搜索蓝牙设备失败', err)
                    reject(err)
                }
            })
        })
    },

    /**
     * 获取处于已连接状态的设备
     */
    getConnectedBluetoothDevices(services) {
        return new Promise((resolve, reject) => {
            wx.getConnectedBluetoothDevices({
                services,
                success: (res) => {
                    console.log('获取处于已连接状态的设备', res)
                    setTimeout(() => {
                        resolve(res.devices)
                    }, 2000)
                },
                fail: (e) => {
                    console.log('获取处于已连接状态的设备失败', e)
                    reject(e)
                }
            })
        })
    },

    /**
     * 连接一个新的蓝牙设备
     * @param currentItem  // 当前要连接的蓝牙设备信息
     */
    createDevice({
        deviceId
    }) {
        console.log('被连接的设备信息', deviceId)

        return new Promise((resolve, reject) => {
            wx.createBLEConnection({
                deviceId,
                timeout: 20000,
                success: (res) => {
                    // 此时已经连接成功
                    console.log('连接设备成功', res)

                    // console.log('checkMe pro')
                    this.initService2cs(deviceId, SERIVCEID).then(() => {
                        
                        const options = {
                            deviceId,
                            serviceId: SERIVCEID,
                            characteristicId: CHARID.NOTIFY,
                        }

                        this.toggleNotify(true, options).then(() => {
                            console.log('开启notify成功')
                            resolve(options)
                        }).catch(e => {
                            console.log('开启notify失败')
                            reject(e)
                        })
                    })
                },
                fail: (e) => {
                    reject(e)
                }
            })
        })
    },

    /**
     * 断开连接一个设备
     * */
    closeDevice(deviceId) {
        return new Promise((resolve, reject) => {
            wx.closeBLEConnection({
                deviceId,
                success: (res) => {
                    this.offOnChange()
                    resolve(res)
                },
                fail: (e) => {
                    reject(e)
                }
            })
        })
    },

    offOnChange() {
        // 取消监听蓝牙适配器状态变化事件
        wx.offBluetoothAdapterStateChange()
        // 取消监听低功耗蓝牙连接状态的改变事件
        wx.offBLEConnectionStateChange()
        // 取消监听低功耗蓝牙设备的特征值变化事件
        wx.offBLECharacteristicValueChange()
    },

    /**
     * 获取服务列表和特征值已完成后续动作
     * */
    initService2cs(deviceId, serviceId,) {
        return new Promise((resolve, reject) => {
            // 获取服务列表
            wx.getBLEDeviceServices({
                deviceId,
                success: s => {
                    console.log(s, 'initService2cs services')
                    console.log('serviceId', serviceId)
                    wx.getBLEDeviceCharacteristics({
                        deviceId,
                        serviceId: serviceId.toUpperCase(),
                        success: c => {
                            console.log('getBLEDeviceCharacteristics', c)
                            resolve({s, c})
                        },
                        fail: e => {
                            reject(e)
                        }
                    })
                },
                fail: e => {
                    reject(e)
                }
            })
        })
    },
    
    /**
     * 连接后获取设备 MAC 地址
     * @param {Array} deviceId 设备ID
     * @param {Array} serviceId 服务ID
     * @param {String} characteristicId 特征值ID
     * */
    getMacDir({
        deviceId,
        serviceId,
        characteristicId
    }, callback) {
        wx.onBLECharacteristicValueChange((res) => {
            console.log('二进制数据值：', res)
            let hexArr = this.ab2hexArr(res.value)
            console.log('MAC地址值', hexArr)
            callback(hexArr)
        })

        wx.readBLECharacteristicValue({
            deviceId,
            serviceId,
            characteristicId,
            success: (res) => {
                console.log(
                    '读取低功耗蓝牙设备的特征值的二进制数据值成功',
                    res
                )
            },
            fail: () => {
            }
        })
    },

    /**
     * 关闭/开启notify 默认开启
     * @param state {Boolean}  @default true -开启/关闭Notify
     * @param options {Object}  @default {}
     * */
    toggleNotify(state = true, options = {}) {
        const { deviceId, serviceId, characteristicId } = options
        return new Promise((resolve, reject) => {
            // console.log('wx.notifyBLECharacteristicValueChange', state, serviceId, deviceId, characteristicId)
            wx.notifyBLECharacteristicValueChange({
                state,
                deviceId,
                serviceId,
                characteristicId,
                success: (res) => {
                    resolve(res)
                },
                fail: (e) => {
                    reject(e)
                }
            })
        })
    },

    /**
     * 指令发送到蓝牙
     * @param value {String} 要发送字符串
     */
    sendDataToBLE(value) {
        const connectionItem = app.globalData.balanceData.connectionItem
        const { deviceId, serviceId, characteristicId } = connectionItem
        return new Promise((resolve, reject) => {
            if (!connectionItem) {
                reject({
                    message: '未连接设备'
                })
                return
            } else {
                if (!deviceId || !serviceId || !characteristicId) {
                    reject({
                        message: '缺少必要参数',
                        detail: { deviceId, serviceId, characteristicId }
                    })
                    return
                }
            }
            console.log('发送的数据------------------------------')
            console.log(value, '发送的数据1------------------------------')
            const buffer = this.string2buf(value)
            console.log('发送的Buffer数据-----------------------------')
            console.log(buffer)
            wx.writeBLECharacteristicValue({
                deviceId: deviceId,
                serviceId: serviceId,
                characteristicId: characteristicId,
                value: buffer,
                success: (res) => {
                    console.log('发送成功', res)
                    resolve(res)
                },
                fail: (e) => {
                    console.error('发送失败', e)
                    reject(e)
                }
            })
        })
    },

    sendDataToBLECb(value, cb) {
        console.log(value)
        console.log('------------sss222')
        // 先取消监听
        wx.offBLECharacteristicValueChange()
        wx.onBLECharacteristicValueChange((res) => {
            const resValue = this.buf2string(res.value)
            if (typeof cb === 'function') {
                cb({
                    value: resValue,
                    originValue: res.value
                })
            }
        })
        if (value === false) {
            return
        }
        return this.sendDataToBLE(value)
    },

    /**
     * ArrayBuffer转16进制字符串
     * */
    ab2hex(buffer) {
        return this.ab2hexArr(buffer).join('')
    },
    
    /**
     * ArrayBuffer转16进制字符串数组
     * */
    ab2hexArr(buffer) {
        return Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
            return ('00' + bit.toString(16)).slice(-2)
        })
    },

    /**
     * 字符串转16进制ArrayBuffer
     * */
    string2buf(str) {
        // 将16进制转化为ArrayBuffer
        return new Uint8Array(
            str.match(/[\da-f]{2}/gi).map(function (h) {
                return parseInt(h, 16)
            })
        ).buffer
    },

    /**
     * ArrayBuffer转字符串
     * */
    buf2string(buffer) {
        let arr = Array.prototype.map.call(new Uint8Array(buffer), (x) => x)
        return arr
            .map((char, i) => {
                return String.fromCharCode(char)
            })
            .join('')
    },

    hexStr2Buffer(hexStr) {
        const len = hexStr.length / 2
        const buffer = new ArrayBuffer(len)
        const dataView = new DataView(buffer)
        hexStr.match(/[\da-f]{2}/gi).forEach((h, index) => {
            dataView.setUint8(index, parseInt(h, 16))
        })
        return buffer
    }
}